#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>

snd_pcm_t * open_sound_dev(snd_pcm_stream_t type)
{
	int err;
    unsigned int rate = 44100;
	snd_pcm_t *handle;
	snd_pcm_hw_params_t *hw_params;

    /*!
     * 打开设备
     */
	if ((err = snd_pcm_open (&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
		printf("Can not open dev\n");
        return NULL;
	}

    /*!
     * 分配参数，用来存储硬件设置
     */
	if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
		printf("Can not open nd_pcm_hw_params_malloc\n");
        return NULL;
	}

    /*!
     * 初始化硬件参数
     */	 
	if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) {
		printf("Can not open snd_pcm_hw_params_any\n");
        return NULL;
	}

    /*!
     * 设置数据存放的方式
     */
	if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
		printf("Can not open snd_pcm_hw_params_set_access\n");
        return NULL;
	}

    /*!
     * 设置数据格式
     */
	if ((err = snd_pcm_hw_params_set_format (handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
		printf("Can not open snd_pcm_hw_params_set_format\n");
        return NULL;
	}

    /*!
     * 设置采样率
     */
	if ((err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &rate, 0)) < 0) {
		printf("Can not open snd_pcm_hw_params_set_rate_near\n");
        return NULL;
	}

    /*!
     * 设置通道数据
     */
	if ((err = snd_pcm_hw_params_set_channels (handle, hw_params, 2)) < 0) {
		printf("Can not open snd_pcm_hw_params_set_channels\n");
        return NULL;
	}

    /*!
     * 根据上面的设置信息，填充硬件参数，并初始化
     */	 
	if ((err = snd_pcm_hw_params (handle, hw_params)) < 0) {
		printf("Can not open snd_pcm_hw_params\n");
        return NULL;
	}

	snd_pcm_hw_params_free (hw_params);
	
	return handle;
}

void close_suond_dev(snd_pcm_t *handle)
{
    snd_pcm_close(handle);
}

snd_pcm_t* open_playback(void)
{
    return open_sound_dev(SND_PCM_STREAM_PLAYBACK);
}

snd_pcm_t* open_capture(void)
{
    return open_sound_dev(SND_PCM_STREAM_CAPTURE);
}

int main (int argc, char *argv[])
{
	int err;
	char buf[512];
	snd_pcm_t *playback_handle;
	snd_pcm_t *capture_handle;

    playback_handle = open_playback();
    if (playback_handle == NULL)
    {
        fprintf (stderr, "Can not open for playback\n");
        return -1;
    }

    capture_handle = open_capture();
    if (capture_handle == NULL)
    {
        fprintf (stderr, "Can not open for capture\n");
        return -1;
    }

    if ((err = snd_pcm_prepare (playback_handle)) < 0) {
		fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
			 snd_strerror (err));
        return -1;
    }


    if ((err = snd_pcm_prepare (capture_handle)) < 0) {
		fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
			 snd_strerror (err));
        return -1;
    }
    
    while (1) {
        if ((err = snd_pcm_readi (capture_handle, buf, 128)) != 128) {
			fprintf (stderr, "read from audio interface failed (%s)\n",
				 snd_strerror (err));
	        return -1;
		}

		if ((err = snd_pcm_writei (playback_handle, buf, 128)) != 128) {
			fprintf (stderr, "write to audio interface failed (%s)\n",
				 snd_strerror (err));
            return -1;
		}
	}

	snd_pcm_close (playback_handle);
	snd_pcm_close (capture_handle);
    return 0;
}

